package com.booter.webflux.controller;

import com.booter.webflux.model.Menu;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
public class ProducerCtroller {

    private static List<Menu> list = new ArrayList<>();

    static {
        Menu m = new Menu();
        m.setId("1");
        m.setName("name-1");
        m.setUri("uri-1");
        list.add(m);

        m = new Menu();
        m.setId("2");
        m.setName("name-2");
        m.setUri("uri-2");
        list.add(m);
    }


    @CrossOrigin
    @RequestMapping(value = "flux/index", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> index() {
        return Flux.interval(Duration.ofSeconds(1L)).map(s -> s.toString());
    }

    @CrossOrigin
    @RequestMapping(value = "flux/index2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> index2() {
        return Flux.interval(Duration.ofSeconds(1L)).map(s -> ServerSentEvent.<String>builder().id(UUID.randomUUID().toString()).event("test-event").data(s.toString() + "\n").build());
    }

    @CrossOrigin
    @RequestMapping(value = "flux/index3")
    public Flux<ServerSentEvent<String>> index3() {
        return Flux.interval(Duration.ofSeconds(1L)).map(s -> ServerSentEvent.<String>builder().id(UUID.randomUUID().toString())
                .event("test-event")
                .data(s.toString()).build());
    }


    //模拟参数传递
    @RequestMapping(value = "menu/list", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Menu> list() {
        return Flux.just(list.toArray(new Menu[]{}));
    }


    @RequestMapping(value = "menu/list2")
    public Flux<Menu> list2() {
        return Flux.just(list.toArray(new Menu[]{}));
    }

    @RequestMapping(value = "menu/save")
    public Mono<Menu> save(@RequestBody Mono<Menu> menu) {
        return menu.map(s -> {
            list.add(s);
            return s;
        });
    }


    @RequestMapping(value = "menu/{id}")
    public Flux<Menu> getbyId(@PathVariable String id, ServerHttpRequest request) {
        System.out.println(request.getURI().toString());
        return Flux.just(list).flatMap(s -> Flux.just(s.stream().filter(t -> id.equals(t.getId())).findFirst().get()));
    }

    @RequestMapping(value = "menu/id")
    public Flux<Menu> getbyId2(@RequestParam String id, ServerHttpRequest request) {
        System.out.println(request.getURI().toString());
        return Flux.just(list).flatMap(s -> Flux.just(s.stream().filter(t -> id.equals(t.getId())).findFirst().get()));
    }


    @RequestMapping(value = "menu/ids")
    public Flux<Menu> getbyId3(@RequestParam List<String> ids, ServerHttpRequest request) {
        System.out.println(request.getURI().toString());
        return Flux.just(list).flatMap(s -> Flux.just(s.stream().filter(t -> ids.contains(t.getId())).collect(Collectors.toList()).toArray(new Menu[]{})));
    }

    /**
     * 此种方式传递的list包含[和]，首元素有[ ,末尾元素有],需要特殊处理
     *
     * @param ids
     * @param request
     * @return
     */
    @RequestMapping(value = "menus/{ids}")
    public Flux<Menu> getbyId4(@PathVariable List<String> ids, ServerHttpRequest request) {
        System.out.println(request.getURI().toString());
        return Flux.just(list).flatMap(s -> Flux.just(s.stream().filter(t -> ids.contains(t.getId())).collect(Collectors.toList()).toArray(new Menu[]{})));
    }


}
